#!/export/home/mahdi/pyenvs/t1/bin/python


from __future__ import print_function
import subprocess as sp
import time
import shlex as sx
import os 
import sys
import multiprocessing as mp
from Queue import Queue as Q
import argparse
import logging


__SPACE_MARKER = '!$#!_$#**_'

def grep(pattern, safe_full_path, val, lock):
    try:
        oldcommand = sx.split('grep {0} {1}'.format(pattern, safe_full_path))
        command = undoMakeSafeFIle(oldcommand)
        ps = sp.Popen(command, stdout=sp.PIPE, stderr=sp.PIPE)
        stdout, stderr = ps.communicate()
        retc = ps.returncode
        with lock:
            val.value += 1
        if stdout:
            print('file w/match: {0}'.format(safe_full_path))
        if stderr and retc != 0:
            print('ERROR: {0}'.format(stderr, file=sys.stderr))
        #print(ps.stdout.read(), end=' ')
    except Exception, e:
        print(e)
        if type(e) == KeyboardInterrupt:
            print('\t\tKEYBOARD INTERRUPT')
            sys.exit(1)
            raise KeyboardInterrupt
        pass


def checkRange(arg):
    try:
        value = int(arg)
    except argparse.ArgumentTypeError, e:
        print(str(e), stderr=sys.stderr)
    if value <= 0 or value > 12:
        raise argparse.ArgumentTypeError('must be in range: {1 <= value <= 12}')
    return value


def makeSafeFile(unsafe_full_path):
    if unsafe_full_path.find(' ') == -1:
        return unsafe_full_path
    else:
        return unsafe_full_path.replace(' ', __SPACE_MARKER)

def undoMakeSafeFIle(cmdlist):
    return [ci.replace(__SPACE_MARKER, ' ') for ci in cmdlist]



if __name__ == '__main__':
    start = time.time()
    parser = argparse.ArgumentParser(description='Recursive wrapper for unix grep command.')
    parser.add_argument('pattern', help='search pattern')
    parser.add_argument('directory', help='the root directory to start the search in')
    parser.add_argument('-c', '--cores', type=checkRange, help='number of cores to use in search range = {1 <= cores <= 12}', default=4)
    #parser.add_argument('--cores', help='will try to use this many cores')
    args = parser.parse_args()
    pool = mp.Pool(args.cores)
    manager = mp.Manager()
    val = manager.Value('i', 0)
    lock = manager.Lock()
    try:
        for root, dirs, fyles in os.walk(args.directory):
            for fyle in fyles:
                unsafe_full_path = os.path.join(root, fyle)
                safe_full_path = makeSafeFile(unsafe_full_path)
                pool.apply_async(grep, args=(args.pattern, safe_full_path, val, lock))
        pool.close()
        pool.join()
    except KeyboardInterrupt, e:
        print('\t\t**INTERRUPTED**')
        sys.exit(1)
    end = time.time()
    print('{0}{1}cores used: {2}'.format('\n'*2, '\t', args.cores))
    print('{0}{1}files processed: {2}'.format('\n'*2, '\t', val.value))
    print('{0}{1}finished in: {2} seconds'.format('\n'*2, '\t', end-start))

